package com.bardsoftware.foronuvolo.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.json.JSONException;
import org.json.JSONObject;

import com.bardsoftware.foronuvolo.data.ForumUser;
import com.google.appengine.api.memcache.InvalidValueException;


public class UserService {
    private static Cache ourCache;

    static {
        try {
            ourCache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
        } catch (CacheException e) {
            e.printStackTrace();
            ourCache = null;
        }
    }
    public static ForumUser getUser(HttpServletRequest req) {
        ForumUser user;
        Object sessionUserID = req.getSession().getAttribute("user_id");
        if (sessionUserID == null) {
            user = fetchUserFromCookie(req);
        } else {
            user = fetchUserByID(sessionUserID.toString());
        }
        if (user == null) {
            user = ForumUser.ANONYMOUS;
        } else {
            req.setAttribute("user_id", user.getID());
        }
        return user;
    }

    public static void getUsers(Map<String, ForumUser> user_id2object) {
        List<String> notCached = new ArrayList<String>();
        for (String id : user_id2object.keySet()) {
            ForumUser cachedUser = fetchFromCache(id);
            if (cachedUser == null) {
                notCached.add(id);
            } else {
                user_id2object.put(id, cachedUser);
            }
        }
        if (!notCached.isEmpty()) {
            Collection<ForumUser> forumUsers = ForumUser.find(notCached);
            for (ForumUser user : forumUsers) {
                user_id2object.put(user.getID(), user);
                cache(user);
            }
        }
    }

    private static void cache(ForumUser user) {
        if (ourCache == null || user == null) {
            return;
        }
        ourCache.put(user.getID(), user);
    }

    private static ForumUser fetchFromCache(String id) {
        if (ourCache == null) {
            return null;
        }
        try {
            return (ForumUser) ourCache.get(id);
        }
        catch (InvalidValueException e) {
            return null;
        }
    }

    public static ForumUser fetchUserByID(String id) {
        ForumUser user = fetchFromCache(id);
        if (user == null) {
            user = ForumUser.find(id);
            cache(user);
        }
        return user;
    }

    private static ForumUser fetchUserFromCookie(HttpServletRequest req) {
        String cookieName = "fcauth" + ForoNuvoloConstants.FRIEND_CONNECT_SITE_ID;
        Cookie authCookie = null;
        if (req.getCookies() == null) {
            return null;
        }
        for (Cookie cookie : req.getCookies()) {
            if (cookieName.equals(cookie.getName())) {
                authCookie = cookie;
                break;
            }
        }
        if (authCookie == null) {
            return null;
        }
        String cookieStringValue = authCookie.getValue();
        String restString = "http://www.google.com/friendconnect/api/people/@me/@self?fcauth=" + cookieStringValue;

        try {
            URL restUrl = new URL(restString);
            URLConnection restCon = restUrl.openConnection();
            BufferedReader restRead = new BufferedReader(new InputStreamReader(restCon.getInputStream()));
            StringBuilder textResponse = new StringBuilder();
            for (String line = restRead.readLine(); line != null; line = restRead.readLine()) {
                textResponse.append(line);
            }
            JSONObject json = new JSONObject(textResponse.toString());
            JSONObject entry = json.getJSONObject("entry");
            String id = entry.getString("id");
            ForumUser result = ForumUser.find(id);
            if (result == null) {
                result = new ForumUser(id, entry.getString("displayName"));
                cache(result);
                result.save();
            }
            return result;
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}
